#include "qqmusic.h"
#include "ui_qqmusic.h"
#include<QMouseEvent>
#include<QDebug>
#include<QWidget>
#include<QGraphicsDropShadowEffect>
#include<QJsonObject>
#include<QJsonArray>
#include<QFileDialog>
#include<QDebug>
#include<QMediaPlayer>
#include<QMediaPlaylist>
#include<QPropertyAnimation>
#include"musiclist.h"
#include"commonpage.h"
#include"volumetool.h"
#include"lrcpage.h"
#include<QSqlError>
#include<QSqlQuery>
#include<QSystemTrayIcon>
#include<QMenu>

QQMusic::QQMusic(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::QQMusic)
{
    ui->setupUi(this);
    //初始化界面

    initUi();

    //初始化播放区域
    InitSqlite();
    initMusicList();
    initPlayer();

    ConnectSignalsAndSlots();



}

QQMusic::~QQMusic()
{
    delete ui;
}

void QQMusic::initUi()
{
    //将标题栏去掉,此函数会带来两个问题
    //1:导致我们的程序无关闭按钮 解决:给按钮建立关闭的槽函数
    //2:无法用鼠标左键移动窗口
    this->setWindowFlags(Qt::FramelessWindowHint);
    setWindowIcon(QIcon(":/image/musicLogo.png"));
    //将程序添加到系统托盘上
    QSystemTrayIcon * trayicon=new QSystemTrayIcon(this);
    trayicon->setIcon(QIcon(":/image/musicLogo.png"));
    //给托盘设置两个菜单项, 退出和显示
    QMenu* menu1=new QMenu(this);
    menu1->addAction("还原", this, &QWidget::showNormal);
     menu1->addSeparator();
     menu1->addAction("退出", this, &QQMusic::quitQQMusic);
     trayicon->setContextMenu(menu1);

    trayicon->show();//在托盘上显示


    //设置阴影之前需要将窗口的背景设置为透明,因为窗口默认的「矩形不透明背景」会把阴影本身裁掉，必须先让窗口背景透明
    setAttribute(Qt::WA_TranslucentBackground);
    RandomPicture();
    //给窗口设置阴影
    QGraphicsDropShadowEffect* shadowEffect(new QGraphicsDropShadowEffect(this));
    shadowEffect->setOffset(0,0);//设置阴影的偏移量
    shadowEffect->setColor("#0000000");//设置阴影的颜色
    shadowEffect->setBlurRadius(10);//设置阴影的半径
    this->setGraphicsEffect(shadowEffect);

    //给按钮添加图片与文本
    ui->rec->setIconAndText(":/image/rec.png","推荐",0);
    ui->music->setIconAndText(":/image/music.png","音乐馆",2);
    ui->audio->setIconAndText(":/image/audio.png","电台",1);
    ui->like->setIconAndText(":/image/like.png","我喜欢",3);
    ui->recent->setIconAndText(":/image/recent.png","最近播放",5);
    ui->local->setIconAndText(":/image/local.png","本地下载",4);


    //添加默认的页面

    ui->stackedWidget->setCurrentIndex(4);
    currentPage=ui->localPage;//设置开始的页面为4
    //添加默认的动画效果
    ui->local->ShowAnimation();
    srand(time(nullptr));
    //设置recBOXitem
    QJsonArray arr=RandomPicture();
    ui->recMusicBox->initRecBoxUi(arr,1);
    ui->supplyMusicBox->initRecBoxUi(RandomPicture(),2);

    //给公共页面进行初始化
    ui->likePage->setCommonPage("我喜欢",QString(":/image/ILike.png"));
    ui->localPage->setCommonPage("本地下载",QString(":/image/musicPlayer.png"));
    ui->recentPage->setCommonPage("最近播放",QString(":/image/recentPlay.png"));
    volumetool=new VolumeTool(this);
    lrcPage=new LrcPage(this);
    lrcPage->hide();
    ui->play->setIcon(QIcon(":/image/on_pause.png"));

    //播放全体按钮信号的捕获
    connect(ui->likePage,&CommonPage::playAll,this,&QQMusic::onPlayAll);
    connect(ui->localPage,&CommonPage::playAll,this,&QQMusic::onPlayAll);
    connect(ui->recentPage,&CommonPage::playAll,this,&QQMusic::onPlayAll);

    //建立与volumeTool工具相关的槽函数
    connect(volumetool,&VolumeTool::setIsMuted,this,&QQMusic::setIsMuted);
    connect(volumetool,&VolumeTool::setMusicVolume,this,&QQMusic::setPlayerVolume);

    //连接进度条有关的槽函数
    connect(ui->progressBar,&MusicSilder::setMusicPos,this,&QQMusic::onMusicSilderPosChanged);

}

void QQMusic::initPlayer()
{
    player=new QMediaPlayer(this);
    playList=new QMediaPlaylist(this);

    //设置播放器播放模式
    playList->setPlaybackMode(QMediaPlaylist::Loop);
    //给播放器设置播放列表
    player->setPlaylist(playList);
    player->setVolume(20);
    ui->playMode->setIcon(QIcon(":/image/repeat.png"));
    //关联与播放区域的信号槽
    connect(player,&QMediaPlayer::stateChanged,this,&QQMusic::OnPlayStateChanged);
    connect(ui->playMode,&QPushButton::clicked,this,&QQMusic::OnPlayBackMode);

    connect(playList,&QMediaPlaylist::currentIndexChanged,this,&QQMusic::OncurrentIndexChanged);

    //播放源时间改变有关的
    connect(player,&QMediaPlayer::durationChanged,this,&QQMusic::onDurationChanged);
    connect(player,&QMediaPlayer::positionChanged,this,&QQMusic::onPositionChanged);
    //当歌曲进行切换时
    connect(player,&QMediaPlayer::metaDataAvailableChanged,this,&QQMusic::onMetaDataAvailableChangedChanged);
}

void QQMusic::initMusicList()
{
    ReadDB();
    ui->likePage->setPageType(PageType::LIKE_PAGE);
    ui->likePage->reFresh(musicList);
    ui->localPage->setPageType(PageType::LOCAL_PAGE);
    ui->localPage->reFresh(musicList);
    ui->recentPage->setPageType(PageType::HISTORY_PAGE);
    ui->recentPage->reFresh(musicList);
}

void QQMusic::InitSqlite()
{
    //创建数据库连接,指明驱动类型
    sqlite=QSqlDatabase::addDatabase("QSQLITE");

    sqlite.setDatabaseName("MusicInfo.db");

    if(!sqlite.open())
    {
        qDebug()<<"数据库打开失败"<<":"<<sqlite.lastError();
    }
     qDebug()<<"数据库打开成功";


     QSqlQuery query(sqlite);//默认打开sqlite这个数据库
      //创建表格
     //ID
     // QString musicId;
     //     QUrl musicUrl;//音乐在磁盘中的路径
     //     QString musicName;//音乐名
     //     QString musicSinger;//歌手名
     //     QString musicAlumn;//音乐专辑名称
     //     qint64  musicTime;//音乐的总时间 ms
     //     bool IsLike;//标记该歌曲是否为喜欢
     //     bool IsHistory;//标记该歌曲是否为历史播放
     query.prepare("CREATE TABLE IF NOT EXISTS MusicInfo\
                   (id INTEGER PRIMARY KEY AUTOINCREMENT,\
                     musicName VARCHAR(50),\
                     musicSinger VARCHAR(50),\
                     musicAlumn VARCHAR(50),\
                     musicTime BIGINT,\
                     IsLike INTEGER,\
                     IsHistory INTEGER, \
                     musicUrl VARCHAR(50),\
                     musicId  VARCHAR(50) )");
       //执行创建表格的语句
      if(!query.exec())
     {
         qDebug()<<"创建表格失败"<<query.lastError();
         return;
     }
     qDebug()<<"创建表格成功";

}

void QQMusic::mousePressEvent(QMouseEvent *event)
{
    //获取相对位置  鼠标光标在窗口的位置-widget相对与窗口的位置
    //如果是左键按着才计算
    if(event->button()==Qt::LeftButton)
    {
        drag=true;
        dragPosition=event->globalPos()-(this->frameGeometry().topLeft());
        return;
    }
    QWidget::mousePressEvent(event);
}

void QQMusic::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons()==Qt::LeftButton&&drag) //drag防止窗口乱移动
    {
        this->move(event->globalPos()-dragPosition);
        return;
    }
    QWidget::mouseMoveEvent(event);

}
//信号与槽连接的槽函数
void QQMusic::ConnectSignalsAndSlots()
{
    connect(ui->rec,&btForm::MouseClicked,this,&QQMusic::handler);
    connect(ui->audio,&btForm::MouseClicked,this,&QQMusic::handler);
    connect(ui->music,&btForm::MouseClicked,this,&QQMusic::handler);
    connect(ui->like,&btForm::MouseClicked,this,&QQMusic::handler);
    connect(ui->local,&btForm::MouseClicked,this,&QQMusic::handler);
    connect(ui->recent,&btForm::MouseClicked,this,&QQMusic::handler);

    connect(ui->likePage,&CommonPage::updateLikeMusic,this,&QQMusic::OnUpdateLikeMusic);
    connect(ui->recentPage,&CommonPage::updateLikeMusic,this,&QQMusic::OnUpdateLikeMusic);
    connect(ui->localPage,&CommonPage::updateLikeMusic,this,&QQMusic::OnUpdateLikeMusic);

    //与双击事件有关的信号槽
    connect(ui->likePage, &CommonPage::playMusicByIndex, this,
    &QQMusic::playMusicByindex);
     connect(ui->localPage, &CommonPage::playMusicByIndex, this,
    &QQMusic::playMusicByindex);
     connect(ui->recentPage, &CommonPage::playMusicByIndex, this,
    &QQMusic::playMusicByindex);


}

void QQMusic::playAllOfCommonPage(CommonPage *page, int index)
{
    currentPage=page;
    updateAnimation();
    playList->clear();
    page->addMusicToPlayList(musicList,playList);

    playList->setCurrentIndex(index);

    player->play();

}

//生成随机的图片,并返回管理好的JSonArray对象
QJsonArray QQMusic::RandomPicture()
{
    QVector<QString> imageNames;
    //使用<<将图片的名字写入 imageNames
    imageNames<<"001.png"<<"002.png"<<"003.png"<<"004.png"
              <<"005.png"<<"006.png"<<"007.png"<<"008.png"
              <<"009.png"<<"010.png"<<"011.png"<<"012.png"
              <<"013.png"<<"014.png"<<"015.png"<<"016.png"
              <<"017.png"<<"018.png"<<"019.png"<<"020.png";
    //打乱imageNames数组中图片名
    std::random_shuffle(imageNames.begin(),imageNames.end());
    QJsonArray objarray;
    for(int i =0;i<imageNames.size();i++)
    {
        QJsonObject obj;
        obj.insert("path",":/recimage/"+imageNames[i]);
        QString strText=QString("推荐-%1").arg(i+1,3,10,QChar('0'));
        obj.insert("text",strText);
        //添加到数组中
        objarray.append(obj);
    }
    return objarray;

}

void QQMusic::handler(int pageid)
{
    //改变层叠窗口
    ui->stackedWidget->setCurrentIndex(pageid);
    //去掉之前btForm的颜色
    QList<btForm*> ListForms=this->findChildren<btForm*>();
    for(auto e:ListForms)
    {
        if(e->getId()!=pageid)
        {
            //清空颜色
            e->clearColor();
        }

    }
    drag=false;


}

void QQMusic::OnUpdateLikeMusic(bool IsLike, QString musicId)
{
    auto it = musicList.findMusicByMusicId(musicId);
     if(it != musicList.end())
     {
        it->setIsLike(IsLike);
     }
     // 2. 通知三个⻚⾯更新⾃⼰的数据
     ui->likePage->reFresh(musicList);
     ui->localPage->reFresh(musicList);
     ui->recentPage->reFresh(musicList);

}

void QQMusic::OnPlayStateChanged(QMediaPlayer::State state)
{
    if(state==QMediaPlayer::PlayingState)
    {
        ui->play->setIcon(QIcon(":/image/on_play.png"));
    }
    else if(state==QMediaPlayer::PausedState)
    {
        ui->play->setIcon(QIcon(":/image/on_pause.png"));
    }
    else if(state==QMediaPlayer::StoppedState)
    {
        ui->play->setIcon(QIcon(":/image/on_pause.png"));
    }
    else
    {
        qDebug()<<"error ";
    }
}

void QQMusic::OnPlayBackMode()
{

    //单曲循环-->列表循环--->随机播放
    if(playList->playbackMode()==QMediaPlaylist::CurrentItemInLoop)
    {
        //设置单曲循环的图标
        ui->playMode->setToolTip("列表循环");
        ui->playMode->setIcon(QIcon(":/image/repeat.png"));
        playList->setPlaybackMode(QMediaPlaylist::Loop);
    }
    else if(playList->playbackMode()==QMediaPlaylist::Loop)
    {
        //循环播放
        ui->playMode->setIcon(QIcon(":/image/random.png"));
        ui->playMode->setToolTip("随机播放");
        playList->setPlaybackMode(QMediaPlaylist::Random);

    }
    else if(playList->playbackMode()==QMediaPlaylist::Random)
    {
        //随机播放
        ui->playMode->setIcon(QIcon(":/image/repeatsingle.png"));
        ui->playMode->setToolTip("单曲循环");
        playList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);

    }
    else
    {
        qDebug()<<"暂不支持";
    }
}

//根据page的不同播放不同的列表
void QQMusic::onPlayAll(PageType pagetype)
{
    CommonPage* page;
    switch (pagetype)
    {
    case LIKE_PAGE:
        page=ui->likePage;
        break;
    case LOCAL_PAGE:
        page=ui->localPage;
        break;
    case HISTORY_PAGE:
        page=ui->recentPage;
        break;
    }
    playAllOfCommonPage(page,0);


}

void QQMusic::OncurrentIndexChanged(int index)
{
    this->index=index;
    //index就是播放列表中的索引,因为commpage中musicOFpage的添加是遍历musiclist得到的
    QString musicId=currentPage->getMusicIdByIndex(index);
    auto it=musicList.findMusicByMusicId(musicId);
    if(it!=musicList.end())
    {
        //找到了
        it->setIsHistory(true);
    }

    ui->recentPage->reFresh(musicList);


}

void QQMusic::playMusicByindex(CommonPage *page, int index)
{

    playAllOfCommonPage(page,index);
}

void QQMusic::setIsMuted(bool ismuted)
{
    player->setMuted(ismuted);
}

void QQMusic::setPlayerVolume(int volumeRatio)
{
    player->setVolume(volumeRatio);
}

void QQMusic::onDurationChanged(qint64 duration)
{
    this->totalTime=duration;
    ui->totalTime->setText(QString("%1:%2").arg(duration/1000/60,2,10,QChar('0'))
                           .arg(duration/1000%60,2,10,QChar('0')));

}

void QQMusic::onPositionChanged(qint64 position)
{
    ui->currentTime->setText(QString("%1:%2").arg(position/1000/60,2,10,QChar('0'))
                             .arg(position/1000%60,2,10,QChar('0')));
    ui->progressBar->moveStep(position/(float)totalTime);

    //将lrc文件中的歌曲进行同步
    //如果有歌曲播放的时候才去显示
    if(playList->currentIndex()>=0)
    {
        lrcPage->showLrcWord(position);
    }
}

void QQMusic::onMusicSilderPosChanged(float ration)
{

    qint64 position=ration*totalTime;
    if(position<=totalTime)
    {
        qDebug()<<position;
        ui->currentTime->setText(QString("%1:%2").arg(position/1000/60,2,10,QChar('0'))
                                 .arg(position/1000%60,2,10,QChar('0')));
        player->setPosition(position);
    }
}

//将musiclist中的数据写入数据库
void QQMusic::WriteToDB()
{
    for(auto music:musicList)
    {
        music.insertToDB(sqlite);
    }
}

void QQMusic::ReadDB()
{
    //从数据库文件读取到本地
    QSqlQuery query;

    query.prepare("SELECT musicName,musicSinger,musicAlumn,musicTime,IsLike,IsHistory,musicUrl,musicId FROM MusicInfo");

    //一行一行进行读取
    if(!query.exec())
    {
        qDebug()<<"read error";
        return ;
    }
     qDebug()<<"read success";
    while(query.next())
    {
        Music music;
        music.setMusicName(query.value(0).toString());
        music.setMusicSinger(query.value(1).toString());
        music.setMusicAlumn(query.value(2).toString());
        music.setMusicTime(query.value(3).toLongLong());
        music.setIsLike(query.value(4).toInt());
        music.setIsHistory(query.value(5).toInt());
        music.setMusicUrl("file:///"+query.value(6).toString());
        music.setMusicId(query.value(7).toString());

        musicList.Push_back(music);

        //恢复歌曲路径保存下来
        musicList.Insert(music.getMusicUrl().toLocalFile());
    }


}

void QQMusic::quitQQMusic()
{
    WriteToDB();
    sqlite.close();
    this->close();
}



void QQMusic::on_quit_clicked()
{


    hide();
}

void QQMusic::on_volume_clicked()
{
    //当用户点击这个按钮,生成对应的volumeTool工具
    //默认情况下这个窗口会基于屏幕的位置,所以我们需要将这个窗口移动到qqmusic中
    //1：获取我们按钮的全局坐标(基于屏幕)
    QPoint point=ui->volume->mapToGlobal(QPoint(0,0));

    //2:大概计算我们volume对话框的左上角
    QPoint volumeLeftTop=point-QPoint(volumetool->width()/2,volumetool->height());


    //微调一下我们的窗口
    volumeLeftTop.setX(volumeLeftTop.x()+20);
    volumeLeftTop.setY(volumeLeftTop.y()+10);

    //移动volume窗口
    volumetool->move(volumeLeftTop);


    volumetool->show();
}

//用户添加本地歌曲的槽
void QQMusic::on_addLocal_clicked()
{

    //1:创建文件对话框
    QFileDialog fileDialog;
    fileDialog.setWindowTitle("添加本地音乐");


    //设置文件对话框打开的模式 Qt::saveMode AcceptOpen
    fileDialog.setAcceptMode(QFileDialog::AcceptOpen);

    //设置文件对话框的文件选择模式,可以指定选择文件的数量或者选择文件的类型(文件或目录)
    fileDialog.setFileMode(QFileDialog::ExistingFiles);

    //设置文件对话框默认打开的路径
    QDir dir=QDir::currentPath();
    dir.cdUp();
    dir.cdUp();
    QString musicsPath=dir.path()+"/Musics";
    fileDialog.setDirectory(musicsPath);
    //设置文件过滤器--->打开的时候只显示音乐文件
    //fileDialog.setNameFilter("All cpp文件 (*.cpp )"); 使用这种方式需要知道我们要过滤文件的所有后缀名

    //通过MIME类型来过滤文件,MIME类型是一种标准化的文件类型标识方式(不依赖与扩展名,有利于跨平台)
     QStringList musicMIMEType ;
     musicMIMEType<<"application/octet-stream";  //过滤出所有二进制文件


    fileDialog.setMimeTypeFilters(musicMIMEType);


    //必须要exec(模态对话框) 或show 不然不会显示文件对话框
    if(fileDialog.exec()==QDialog::Accepted)  //用户关闭对话框如果添加了歌曲,我们才将选择的歌曲加入到列表中
    {
        //先将我们的页面切换到本地音乐界面
        ui->stackedWidget->setCurrentIndex(4);

        //获取用户选择的文件有哪些,使用QFileDialog中内置的API
        QList<QUrl> musicUrls=fileDialog.selectedUrls();


        //将我们选中文件的所有url交给音乐模块来处理
        //管理的是解析之后的music对象
        musicList.addMusicByUrl(musicUrls);

        //将music对象添加到对应的页面
        ui->localPage->reFresh(musicList);

        //将musiclist中的音乐添加到列表中
         ui->localPage->addMusicToPlayList(musicList,playList);
    }



}

void QQMusic::on_play_clicked()
{
    //点击时状态为播放状态
    if(player->state()==QMediaPlayer::PlayingState)
    {
        //将状态改为禁止状态
        player->pause();

    }
    //点击时状态为禁止状态
    else if(player->state()==QMediaPlayer::PausedState)
    {
        //改为播放
        player->play();
    }
    //如果状态为停止状态,刚开始默认
    else if(player->state()==QMediaPlayer::StoppedState)
    {
        player->play();
    }
    else
    {
        qDebug()<<"error state";
    }
}

void QQMusic::on_playDown_clicked()
{
    playList->next();
}

void QQMusic::on_playUp_clicked()
{
    playList->previous();
}

void QQMusic::onMetaDataAvailableChangedChanged(bool Available)
{
     //根据index拿到歌曲的singer与name
    auto musicId=currentPage->getMusicIdByIndex(index);
    auto it=musicList.findMusicByMusicId(musicId);
    QString singername;
    QString musicname;
    if(it!=musicList.end())
    {
        singername=it->getMusicSinger();
        musicname=it->getMusicName();
    }

    ui->musicName->setText(musicname);
    ui->musicSinger->setText(singername);

    //获取歌曲的图片
    QVariant image=player->metaData("ThumbnailImage");
    if(image.isValid())
    {
        QImage coverImage=image.value<QImage>();
        ui->musicCover->setPixmap(QPixmap::fromImage(coverImage));
        ui->musicCover->setScaledContents(true);//自动适应歌曲的大小
        currentPage->setImageLabel(QPixmap::fromImage(coverImage));
    }
    else
    {
        //不合法
        QString pathname=":/image/default.png";
        ui->musicCover->setPixmap(pathname);
        ui->musicCover->setScaledContents(true);//自动适应歌曲的大小
        currentPage->setImageLabel(pathname);
    }

    //歌曲进行切换时,需要重新对歌词进行解析
    //歌曲必须存在
    if(it!=musicList.end())
    {
        lrcPage->phraseLrcfile(it->getLrcFilePath());
        lrcPage->SetSigner(it->getMusicSinger());
        lrcPage->SetmusicName(it->getMusicName());
    }
}


//按下歌词按钮的槽函数
void QQMusic::on_lrcWord_clicked()
{
   //以动画的形式将lrcpage给显示出来
   QPropertyAnimation* animation=new QPropertyAnimation(lrcPage,"geometry",this);
   animation->setDuration(500);//设置动画的持续时长
   animation->setStartValue(QRect(10,10+lrcPage->height(),lrcPage->width(),lrcPage->height()));
   animation->setEndValue(QRect(10,10,lrcPage->width(),lrcPage->height()));
   animation->start();
   connect(animation,&QPropertyAnimation::finished,this,[=]{delete animation;});
   lrcPage->show();


}

void QQMusic::on_min_clicked()
{
    showMinimized();
}

void QQMusic::updateAnimation()
{
    //算出current现在的索引
    int index =ui->stackedWidget->indexOf(currentPage);
    if(index==-1)
    {
        qDebug()<<"error code prev";
    }

    QList<btForm*> btforms=findChildren<btForm*>();
    for(auto e:btforms)
    {
        if(e->getId()==index)
        {
            e->ShowAnimation();
        }
        else
        {
            e->hideAnimation();
        }
    }
}
